package br.com.almanach.jsf;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

public class RecursoPhaseListener implements PhaseListener  {

    private static final String RESOURCE_PREFIX = "/recurso/imagem/";
    //Location of where the js, img, css etc files reside inside the jar, we could also placed them in META-INF folder
    private static final String RESOURCE_PATH = "C:\\imagens\\";
    public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
    private Map<String, String> extensionToContentType = null;

    /** Creates a new instance of ResourcePhaseListener */
    public RecursoPhaseListener() {
        init();
    }

    private void init() {
        extensionToContentType = new HashMap<String, String>();
        extensionToContentType.put(".js", "text/javascript");
        extensionToContentType.put(".gif", "image/gif");
        extensionToContentType.put(".jpg", "image/jpeg");
        extensionToContentType.put(".jpeg", "image/jpeg");
        extensionToContentType.put(".png", "image/png");
        extensionToContentType.put(".txt", "text/plain");
        extensionToContentType.put(".ico", "application/octet-stream");
    }

    private String getContentTypeFromRequest(String resourceName) {
        String result = null;
        int i;

        if (null != resourceName) {
            if (-1 != (i = resourceName.lastIndexOf("."))) {
                result = resourceName.substring(i);
                result = extensionToContentType.get(result);
            }
        }

        if (null == result) {
            result = DEFAULT_CONTENT_TYPE;
        }

        return result;
    }

    @Override
    public void afterPhase(PhaseEvent event){
        //recupera contexto do jsf
        FacesContext facesContext = event.getFacesContext();

        ExternalContext extContext = facesContext.getExternalContext();


        String rootId = facesContext.getViewRoot().getViewId();
        //Clean up key
        String resourceName = rootId.replace(RESOURCE_PREFIX, "");
        resourceName = resourceName.replace(".jspx", "");
        resourceName = resourceName.replace(".jsf", "");

        if (!rootId.startsWith(RESOURCE_PREFIX)) {
            return;
        }

        //Location of resources inside the jar file
        String fileName = RESOURCE_PATH + resourceName;

        //verifica se o arquivo existe
        File f = new File(fileName);

        if (f.exists()) {
            try {
                //transforma arquivo em input stream
                InputStream resourceStream = new FileInputStream(f);

                HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
                response.setCharacterEncoding(extContext.getRequestCharacterEncoding());
                ServletOutputStream sos = null;
                try {
                    sos = response.getOutputStream();
                    if (resourceStream != null) {
                        response.setStatus(HttpServletResponse.SC_OK);
                        //Resolve mime type, required that we have activation.jar loaded
                        //Additional mime types can be defined in /META-INF/mimes.types  {@link http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/activation/MimetypesFileTypeMap.html }
                        /*String contentType = new MimetypesFileTypeMap().getContentType(fileName);
                        System.out.println("contentType: " + contentType);
                        response.setContentType(contentType);*/

                        String contentType = getContentTypeFromRequest(resourceName);
                        response.setHeader("Cache-Control", "cache, must-revalidate");
                        response.setHeader("Pragma", "public");
                        response.setContentType(contentType);

                        byte[] buffer = new byte[1024];
                        for (int bytesRead = 0; (bytesRead = resourceStream.read(buffer, 0, buffer.length)) > 0;) {
                            sos.write(buffer, 0, bytesRead);
                        }
                    } else {
                        //Resource not found
                        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        response.setContentType(getContentTypeFromRequest(resourceName));
                    }
                    sos.flush();
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (FileNotFoundException ex) {
                Logger.getLogger(RecursoPhaseListener.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        event.getFacesContext().responseComplete();

    }

    @Override
    public void beforePhase(PhaseEvent event) {
    }

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.UPDATE_MODEL_VALUES;
    }

}
